<?php
/**
 * 数据库实现类，提供对Mysql的底层操作
 * 
 * @category  Gi
 * @package   Core
 * @author    jufei <jufeis@gmail.com>
 * @version   $Id$
 */
final class Db{

	/*-------私有成员------*/
	private static $_queryConter = 0;		//每页执行query的数目
	
	private $_linkId = 0;		//连接句柄
	private $_queryId = 0;		//查询句柄
	private $_dbConfig;
	private $_pConn = 0;
	private static $_instance = array();
		
	/**
	 * 构造函数设为私有。 只有用getInstance才能实例化本类
	 */
	private function __construct() {}
	
    /**
     * 取得数据库操作类实例,单件模式
     */
    public static function getInstance($dbConfig = null)
    {
    	$dbConfig = self::_parseConfig($dbConfig);
        $uniqueId = _toUniqueId($dbConfig);
        if (!self::$_instance[$uniqueId]){
        	$className = __CLASS__;
        	$db = new $className();
        	$db->connect($dbConfig);
        	self::$_instance[$uniqueId] = $db;
        }
        return self::$_instance[$uniqueId];
    }
    
    private function _parseConfig($dbConfig){
    	if(!is_array($dbConfig)){
    		$dbConfig = array();
    	}
    	
		$_dbConfig = array (
            'DB_TYPE'	=>   C('DB_TYPE'),
            'DB_USER'  	=>   C('DB_USER'),
            'DB_PWD'   	=>   C('DB_PWD'),
            'DB_HOST'  	=>   C('DB_HOST'),
            'DB_PORT'   =>   C('DB_PORT'),
            'DB_NAME'	=>	 C('DB_NAME'),
            'TB_PREFIX'	=>   C('TB_PREFIX'),
        );
        
    	return array_merge($_dbConfig,$dbConfig);
    }
    
    /**
     * 连接数据库
     *
     * @param array $dbConfig
     * @return resource
     */
    public function connect($dbConfig)
    {
    	$this->_dbConfig = $dbConfig;
    	$dbport = $dbConfig['DB_PORT'] ? $dbConfig['DB_PORT'] : '3306';
    	$dbHost = $dbConfig['DB_HOST'] . ":" . $dbport;
    	$dbName = $dbConfig['DB_NAME'];
    	$dbUser = $dbConfig['DB_USER'];
    	$dbPwd  = $dbConfig['DB_PWD'];
		if($this->_pConn)
			$this->_linkId = @mysql_pconnect($dbHost, $dbUser, $dbPwd) or $this->halt($this->error());
		else
			$this->_linkId = @mysql_connect($dbHost, $dbUser, $dbPwd) or $this->halt($this->error());
		if(!empty($dbName)){
			$this->selectDb($dbName);
		}
		$this->query("SET NAMES UTF8",$this->_linkId);
		return $this->_linkId;
    }

	function selectDb($dbName)
	{
		$this->_queryId = $this->query("use `$dbName`");
		$this->_dbName = $dbName;
		Return $this->_queryId;
	}

	function getCurrentDbName()
	{
		$data = $this->fetch_one_array("select DATABASE() as _dbName");
		$this->_dbName = $data['_dbName'];
		return  $data['_dbName'];
	}
	
	/**
	 * 查询表的主键名
	 * @param string $tbName
	 * @return string
	 */
	function getPkName($tbName){
		$SQL = "describe $tbName";
		$this->query($SQL);
		while( $row=$this->fetchArray()){
			if($row['Key']=='PRI'){
				return $row['Field'];
			}
		} 
		return "";
	}

	/**
	 * 执行一条query;对于select的语句，系统会自动替换#@_为数据表的前缀.
	 * @param string $sql
	 * @param resource $linkId
	 * @return resourceID
	 */
	function query($sql, $linkId = '')
	{
		empty($linkId) && $linkId = $this->_linkId;
		_trace($sql,"SQL");
		$sql = trim($sql);
		if (strtolower(substr($sql,0,6)) == "select") {
			$sql = str_replace("#@_",$this->_dbConfig,$sql);
		}
		$this->_queryId = mysql_query($sql,$linkId) or $this->halt("Query wrong",$this->error());
		self::$_queryConter++;
		Return $this->_queryId;
	}
	
	/**
	 * 顺序读取资源的每一行到数组
	 * @param resource $qid
	 * @param int $result_type 默认为关联数组
	 * @return array
	 */
	function fetchArray($qid = '',$result_type = MYSQL_ASSOC) 
	{
		if(!$qid)$qid=$this->_queryId;
		Return mysql_fetch_array($qid, $result_type);
	}
	
	/**
	 * 获取query的第一列的值
	 * @param string $sql
	 * @param resource $linkId
	 * @return string|int|float
	 */
	function getVar($sql,$linkId="")
	{
		$data = $this->getRow($sql, $linkId);
		return current($data);
	}
	
	/**
	 * 获取query的第一行的值
	 * @param string $sql
	 * @param resource $linkId
	 * @return array
	 */
	function getRow($sql,$linkId="") 
	{
		$this->query($sql, $linkId);
		return $this->fetchArray();
	}
	
	/**
	 * 获取query的所有行
	 * @param string $sql
	 * @param resource $linkId
	 * @return array
	 */
	function getAllRows($sql,$linkId="")
	{
		$data = array();
		$this->query($sql, $linkId);
		while($row = $this->fetchArray()){
			$data[] = $row;
		}
		return $data;
	}
	
	function error() 
	{
		Return mysql_error();
	}

	function errno() 
	{
		Return intval(mysql_errno());
	}

	function result($row) 
	{
		$this->query_result = @mysql_result($this->_queryId, $row);
		Return $this->query_result;
	}

	function numRows($qid='') 
	{
		if(!$qid)$qid=$this->_queryId;
		$num_rows = mysql_num_rows($qid);
		Return $num_rows;
	}

	function numFields($qid='') 
	{
		if(!$qid)$qid=$this->_queryId;
		Return mysql_num_fields($qid);
	}

	function freeResult($qid='') 
	{
		if(!$qid)$qid = $this->_queryId;
		Return mysql_free_result($this->_queryId);
	}

	function insertId() 
	{
		$this->insert_id = mysql_insert_id();
		Return $this->insert_id;
	}

	function dataSeek($row) 
	{
		Return mysql_data_seek($this->_queryId,$row);
	}
	function close() 
	{
		Return mysql_close();
	}
	function affectedRows() 
	{
		Return mysql_affected_rows($this->_linkId);
	}	
	/**
	 * 得到一个表的字段列表
	 * @return array
	 * */
	function getTbFields($table)
	{
		$fields = array();
		$this->query( "show fields from $table");	
		while ( $data = $this->fetchArray( '',MYSQL_NUM) ) {
				$fields[] = $data[0];
		}
		return $fields;
	}
	function halt($message = '', $sql = '') 
	{
		throw new GiException("$message<br>$sql");
	}
	
	/**
	 * 检查指定的表是否存在
	 *
	 * @return unknown
	 */
	function isTbExist($table){
		try {
			$this->query( "show fields from $table");
		} catch (GiException $e){
			return false;
		}
		return true;
	}

}